# 同步互斥机制：解决了多个进程或者线程对共享资源的争夺，因为某些共享资源在某个时刻可能只允许一个进程对其进行访问。
# 临界资源：临界资源就是上面提到的，同时只允许一个进程对其进行访问的资源，即：虽然是共享资源，但是不能多个进程同时对资源进行访问和操作。多进程之间需要遵守某些约定来对临界资源进行访问和操作。
# 临界区：临界区就是我们写的多进程代码中，对临界资源进行操作的那一部分代码段(区域)。
# 同步：同步可以理解为是一种合作关系，为了完成某项任务(访问临界资源)，多个进程之间通过合作协调，排好顺序，依次操作。举个例子，在医院的一个诊室外排了很多看病的人，基于重症排在前，轻症排在后的规则排好了顺序，医生就可以看成是一个临界资源，医生每次只能看一个病人(每次只有一个病人(进程)能进诊室看医生(临界资源))，然后依次看完所有的病人。
# 互斥：互斥则是一种制约关系，进程访问临界资源时会上锁，使得其他进程阻塞等待，直到上一个进程退出后解锁，下一个进程才能够访问临界资源。还是上面的例子：在医院的一个诊室外有很多看病的人，并没有按照顺序排着，医生每次只能看一个病人，病人通过争夺抢占看谁先进入诊室，一个病人进入诊室后，就将诊室的门锁上(上锁)，阻止其他病人进入，直到这个病人看完后，打开门出了诊室(解锁)，剩下的病人又开始争夺抢占看谁先进入诊室。

# Event事件
# Event事件通常用于主进程控制其他进程的执行，Event事件主要提供了三个方法set、wait、clear。
# 事件处理的机制：全局定义了一个标志 _flag，如果标志的值为 False，那么当程序执行到wait方法时就会阻塞。如果标志值设为True，那么wait方法便不再阻塞了。
# Event事件对象的set方法将标志设为True，clear方法将标志设置为False，wait方法则是在标志值为False时阻塞等待。
# 主要方法：
# e = Event() 创建事件对象
# e.wait([timeout]) 设置事件阻塞，参数(timeout)：阻塞等待时间。阻塞当前线程的执行，直到_flag被设置为True。只有当_flag = False时，调用wait()才会阻塞当前线程的运行，此时wait()方法相当于pass
# e.set() 事件设置，将_flag（标志位）设置为True，当事件被设置后e.wait()不再阻塞
# e.clear() 清除设置，将_flag设置为False，当事件设置被清除后e.wait又会阻塞
# e.is_set() 事件状态判断，True(wait方法未阻塞)，False(wait方法阻塞)

# 死锁
# 如果程序中多个线程相互等待对方持有的锁，而在得到对方的锁之前都不释放自己的锁，由此导致了这些线程不能继续运行，这就是死锁。 死锁的表现是:程序死循环。
# 防止死锁一般的做法是:如果程序要访问多个共享数据，则首先要从全局考虑定义一个获得锁的顺序，并且在整个程序中都遵守这个顺序。释放锁时，按加锁的反序释放即可。
# 所以必须是有两个及其以上的的并发线程，才能出现死锁，如果是多于2 个线程之间出现死锁，那他们请求锁的关系一定是形成了一个环，比如A 等B的锁，B等C的锁，C等A的锁。

# 主线程控制子线程的执行
# https://www.cnblogs.com/guyexiangyun/p/10587074.html
import threading
import time
# 全局变量
event = threading.Event()


def foo():
    # 开启子线程t时打印这句话
    print("wait server... at ", time.ctime())
    print(event.is_set())
    # 阻塞子线程的执行，此时event中的标志位为False
    event.wait()
    print("connect to server... at ", time.ctime())


if __name__ == '__main__':

    t = threading.Thread(target=foo, args=())
    # 开启一个子线程
    t.start()
    # 主线程休眠3秒
    time.sleep(3)
    # 在foo函数中的event.wait()后打印这句话，此时子线程被阻塞
    print("start server successfully... at ", time.ctime())
    # 主线程继续休眠3秒
    time.sleep(3)
    # 将event中的标志位设置为True，foo函数中的最后一句话就被打印了。
    event.set()
    # 事件状态判断，True(wait方法未阻塞)，False(wait方法阻塞)
    print(event.is_set())
